package com.gitee.wsl.android.ui.ext

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.StringRes
import com.gitee.wsl.android.ui.ext.ToastInit.fixBadTokenException


object ToastInit {

    fun initToast(initToast:ToastInterface?){
        initToast?.let { toastImpl = it }
    }

    interface ToastInterface{
        fun toast(context:Context,  text:String, duration:Int)

        fun toast(context:Context, @StringRes resId:Int, duration:Int)

        fun toastSuccess(context:Context, label:String)

        fun toastError(context:Context, label:String)
    }

    abstract class ToastAdapter:ToastInterface{
        override fun toast(context: Context, @StringRes resId: Int, duration: Int) {
            toast(context,context.getText(resId).toString(),duration)
        }

        override fun toastSuccess(context: Context, label: String) {
            toast(context,label,Toast.LENGTH_SHORT)
        }

        override fun toastError(context: Context, label: String) {
            toast(context,label,Toast.LENGTH_SHORT)
        }
    }

    fun Toast.fixBadTokenException(): Toast = apply {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
            try {
                @SuppressLint("DiscouragedPrivateApi")
                val tnField = Toast::class.java.getDeclaredField("mTN")
                tnField.isAccessible = true
                val tn = tnField.get(this)

                val handlerField = tnField.type.getDeclaredField("mHandler")
                handlerField.isAccessible = true
                val handler = handlerField.get(tn) as Handler

                val looper = checkNotNull(Looper.myLooper()) {
                    "Can't toast on a thread that has not called Looper.prepare()"
                }
                handlerField.set(tn, object : Handler(looper) {
                    override fun handleMessage(msg: Message) {
                        try {
                            handler.handleMessage(msg)
                        } catch (ignored: WindowManager.BadTokenException) {
                        }
                    }
                })
            } catch (ignored: IllegalAccessException) {
            } catch (ignored: NoSuchFieldException) {
            }
        }
    }
}
private var toastImpl: ToastInit.ToastInterface = object : ToastInit.ToastAdapter() {
    override fun toast(context: Context, text:String, duration: Int) {
        Toast.makeText(context, text, duration).fixBadTokenException().show()
    }
}


fun Context.toast(message:String) =
    toastImpl.toast(this,message,Toast.LENGTH_SHORT)

fun Context.toast(@StringRes message: Int) =
    toastImpl.toast(this,message,Toast.LENGTH_SHORT)

fun Context.toastLong(message: String) =
    toastImpl.toast(this,message,Toast.LENGTH_LONG)

fun Context.toastLong(@StringRes message: Int) =
    toastImpl.toast(this,message,Toast.LENGTH_LONG)

fun Context.toastSuccess(label:String)=toastImpl.toastSuccess(this,label)

fun Context.toastError(label:String)=toastImpl.toastError(this,label)

